package sun.scheduler.util.graph.algorithm.maxflow;

/**
 * Represents the Edge data of a {
 *
 * @see Graph} used by network flow algorithms.
 * @param <E> generic type of inner data.
 * @author mfj
 */
public class EdgeFlowImpl<E> implements EdgeFlow
{
    private double flow = 0;

    private double upperCapacity;

    private double lowerCapacity;

    /**
     * The inner data of the edge flow.
     */
    public E innerData;


    /**
     * Instantiates a new {
     *
     * @see EdgeFlow} with the specified (upper-)capacity.
     * @param capacity the initial capacity
     */
    public EdgeFlowImpl(double capacity)
    {
        this.upperCapacity = capacity;
        this.lowerCapacity = 0;
    }


    /**
     * Instantiates a new {
     *
     * @see EdgeFlow} with the specified upper capacity and lower capacity of zero.
     * @param upperCapacity, double lowerCapacity the initial capacity
     */
    public EdgeFlowImpl(double lowerCapacity, double upperCapacity)
    {
        assert (lowerCapacity <= upperCapacity);

        this.lowerCapacity = lowerCapacity;
        this.upperCapacity = upperCapacity;
    }


    /**
     * Gets the lower capacoty of this edge.
     *
     * @return the capacity.
     */
    @Override
    public double getLowerCapacity()
    {
        return lowerCapacity;
    }


    /**
     * Gets the upper capacity of this edge.
     *
     * @return the capacity.
     */
    @Override
    public double getUpperCapacity()
    {
        return upperCapacity;
    }


    /**
     * Gets the flow through this edge.
     *
     * @return the flow through this edge.
     */
    @Override
    public double getFlow()
    {
        return flow;
    }


    /**
     * Sets the flow through this {
     *
     * @see @Edge} to a new flow.
     * @param flow the new flow of this edge
     * @throws IllegalArgumentException if the flow is not within the bounds of the capacity, i.e. {@code flow > capacity}
     */
    public void setFlow(double flow)
    {
        this.flow = flow;
    }


    /**
     * Adds some value to this {
     *
     * @see @Edge}.
     * @param val the value to add
     * @throws IllegalArgumentException if the flow is not within the bounds of the capacity, i.e. {@code flow > capacity}
     */
    @Override
    public void addFlow(double val)
    {
        setFlow(flow + val);
    }


    /**
     * Gets the residual capacity {@code upperCapacity - flow}.
     *
     * @return the residual capacity
     */
    public double forwardResidualCapacity()
    {
        return upperCapacity - flow;
    }


    public double backwardResidualCapacity()
    {
        return flow - lowerCapacity;
    }


    @Override
    public String toString()
    {
        return " [" + lowerCapacity + "/" + flow + "/" + upperCapacity + "]";
    }
}